package com.ccteam.fluidmusic.ui.moment

import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.fragment.app.*
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.ConcatAdapter
import com.bumptech.glide.Glide
import com.ccteam.fluidmusic.NavAlbumDirections
import com.ccteam.fluidmusic.NavPlaylistSheetDirections
import com.ccteam.fluidmusic.R
import com.ccteam.fluidmusic.databinding.FragmentMomentDetailBinding
import com.ccteam.fluidmusic.databinding.MomentDetailParentCommentItemBinding
import com.ccteam.fluidmusic.fluidmusic.common.utils.MediaIDHelper
import com.ccteam.fluidmusic.ui.MainActivityViewModel
import com.ccteam.fluidmusic.ui.moment.comment.PublishCommentFragment
import com.ccteam.fluidmusic.ui.moment.imageview.ImageBrowseActivityDirections
import com.ccteam.fluidmusic.ui.moment.imageview.ImageBrowseData
import com.ccteam.fluidmusic.ui.moment.imageview.ImageViewData
import com.ccteam.fluidmusic.ui.music.MusicInfoViewModel
import com.ccteam.fluidmusic.utils.EventObserver
import com.ccteam.fluidmusic.utils.generateContainerTransform
import com.ccteam.fluidmusic.view.adapters.ViewBindViewHolder
import com.ccteam.fluidmusic.view.adapters.comment.CommentItemCallback
import com.ccteam.fluidmusic.view.adapters.moment.MomentDetailItemCallback
import com.ccteam.fluidmusic.view.adapters.moment.MomentDetailRVAdapter
import com.ccteam.fluidmusic.view.adapters.paging.CustomLoadStateAdapter
import com.ccteam.fluidmusic.view.adapters.paging.PagingAdapter
import com.ccteam.fluidmusic.view.base.LightBounceEdgeEffectFactory
import com.ccteam.fluidmusic.view.bean.LoadMessage
import com.ccteam.fluidmusic.view.bean.PublishCommentData
import com.ccteam.fluidmusic.view.components.CornerImageWrapperView
import com.ccteam.fluidmusic.widget.SNACKBAR_ALL_BOTTOM_BAR
import com.ccteam.fluidmusic.widget.comment.ReplyLayout
import com.ccteam.fluidmusic.widget.snackbar
import com.ccteam.model.moment.MOMENT_SHARE_TYPE_ALBUM
import com.ccteam.model.moment.MOMENT_SHARE_TYPE_MUSIC
import com.ccteam.model.moment.MOMENT_SHARE_TYPE_PLAYLIST
import com.ccteam.model.moment.comment.COMMENT_TYPE_COMMENT
import com.ccteam.model.moment.comment.COMMENT_TYPE_REPLAY
import com.ccteam.model.moment.comment.COMMENT_TYPE_REPLAY_REPLAY
import com.ccteam.shared.result.moment.MomentListItem
import com.ccteam.shared.result.moment.comment.MomentCommentItem
import com.ccteam.shared.result.moment.comment.MomentReplayItem
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject

@AndroidEntryPoint
class MomentDetailFragment : Fragment() {

    private var _binding: FragmentMomentDetailBinding? = null
    private val binding get() = _binding!!

    private val momentDetailViewModel by viewModels<MomentDetailViewModel>()
    private val musicInfoViewModel by viewModels<MusicInfoViewModel>()
    private val mainActivityViewModel by activityViewModels<MainActivityViewModel>()

    @Inject lateinit var lightBounceEdgeEffectFactory: LightBounceEdgeEffectFactory

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setFragmentResultListener(PublishCommentFragment.REFRESH_COMMENT_RESULT){ _, bundle ->
            if(bundle.getBoolean(PublishCommentFragment.REFRESH_COMMENT_RESULT)){
                momentDetailViewModel.refreshCommentDetail()
            }
        }

        // 设置共享动画
        sharedElementEnterTransition = generateContainerTransform(requireContext())
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentMomentDetailBinding.inflate(inflater,container,false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        val detailAdapter = MomentDetailRVAdapter(imageCallback,momentDetailItemCallback)
        val commentAdapter = ParentCommentRVAdapter(parentItemCallback,replayItemCallback)

        binding.toolbarMomentDetail.setNavigationOnClickListener {
            findNavController().navigateUp()
        }

        binding.rvMomentDetail.adapter = ConcatAdapter(detailAdapter,commentAdapter.withLoadStateFooter(
            CustomLoadStateAdapter(commentAdapter ,true){
                commentAdapter.retry()
            }
        ))

        lightBounceEdgeEffectFactory.applyBounceView(binding.rvMomentDetail,this)

        binding.rvMomentDetail.edgeEffectFactory = lightBounceEdgeEffectFactory

        musicInfoViewModel.loadMessage.observe(viewLifecycleOwner,EventObserver{
            when(it){
                is LoadMessage.Loading ->{
                    view.snackbar(R.string.description_moment_music_loading, SNACKBAR_ALL_BOTTOM_BAR, Snackbar.LENGTH_LONG)
                        .show()
                }
                is LoadMessage.Error ->{
                    view.snackbar(R.string.description_moment_music_error, SNACKBAR_ALL_BOTTOM_BAR).show()
                }
                is LoadMessage.Success ->{
                    mainActivityViewModel.addQueueItem(musicInfoViewModel.currentMediaId,
                        MediaIDHelper.ONLINE_MEDIA_CACHE, MediaIDHelper.PLAYLIST_ADD_TYPE_NOW_PLAY)
                }
            }
        })

        momentDetailViewModel.momentDetail.observe(viewLifecycleOwner, {
            detailAdapter.submitList(it)
        })

        momentDetailViewModel.isLogin.observe(viewLifecycleOwner, {
            binding.containerCommentEdit.isVisible = it
        })

        momentDetailViewModel.shouldRefreshComment.observe(viewLifecycleOwner, EventObserver{
            commentAdapter.refresh()
        })

        viewLifecycleOwner.lifecycleScope.launch {
            momentDetailViewModel.commentList.collectLatest {
                commentAdapter.submitData(it)
            }
        }

        viewLifecycleOwner.lifecycleScope.launch {
            commentAdapter.loadStateFlow.collectLatest {
                momentDetailViewModel.setLoadMessage(it.refresh)
            }
        }

        momentDetailViewModel.loadMessage.observe(viewLifecycleOwner, {
            binding.containerCommentEdit.isVisible = it is LoadMessage.NotLoading && momentDetailViewModel.isLogin.value ?: false
            // 朋友圈详情没有加载出来前不显示列表内容
            binding.rvMomentDetail.isVisible = it is LoadMessage.NotLoading

            binding.statusView.changeToLoadingStatus(it is LoadMessage.Loading)
            binding.statusView.changeToErrorStatus(it)
        })

        momentDetailViewModel.upInfo.observe(viewLifecycleOwner, {
            updateUpInfo(it)
        })

        momentDetailViewModel.upLoadMessage.observe(viewLifecycleOwner, EventObserver{
            if(it is LoadMessage.Error){
                view.snackbar(it.errorMessage.description.toString()).show()
            }
        })

        momentDetailViewModel.deleteLoadMessage.observe(viewLifecycleOwner, EventObserver{
            if(it is LoadMessage.Error){
                view.snackbar(it.errorMessage.description.toString()).show()
            } else if(it is LoadMessage.Success){
                Toast.makeText(requireContext().applicationContext,R.string.description_delete_moment_success,Toast.LENGTH_SHORT).show()
                findNavController().navigateUp()
                setFragmentResult(REFRESH_MOMENT_KEY, bundleOf(REFRESH_MOMENT_KEY to true))
            }
        })

        momentDetailViewModel.canDelete.observe(viewLifecycleOwner, {
            binding.toolbarMomentDetail.menu.findItem(R.id.toolbar_moments_delete).isVisible = it
        })

        binding.toolbarMomentDetail.setOnMenuItemClickListener { menuItem ->
            return@setOnMenuItemClickListener when(menuItem.itemId){
                R.id.toolbar_moments_delete ->{
                    // 删除朋友圈
                    MaterialAlertDialogBuilder(requireContext())
                        .setTitle(R.string.description_delete_moment_info)
                        .setMessage(getString(R.string.description_delete_moment))
                        .setNegativeButton(R.string.description_cancel) { _,_ -> }
                        .setPositiveButton(R.string.description_delete) { _,_ ->
                            momentDetailViewModel.deleteMoment()
                        }.show()
                    true
                }
                else ->
                    false
            }
        }

        binding.btnEditComment.setOnClickListener {
            if(!momentDetailViewModel.momentDetail.value.isNullOrEmpty()){
                findNavController().navigate(
                    MomentDetailFragmentDirections.actionMomentDetailFragmentToPublishCommentFragment(
                        PublishCommentData(
                            momentDetailViewModel.momentDetail.value!![0].id,
                            COMMENT_TYPE_COMMENT, null,
                            momentDetailViewModel.momentDetail.value!![0].userName,
                            null
                        )
                    )
                )
            }
        }

        binding.statusView.setRetryClickListener {
            momentDetailViewModel.refreshMomentDetail()
            commentAdapter.refresh()
        }

        binding.btnUp.setOnClickListener {
            if(binding.btnUp.isSelected){
                momentDetailViewModel.cancelMomentUp()
            } else {
                momentDetailViewModel.setMomentUp()
            }
        }
    }

    private fun updateUpInfo(momentUp: MomentDetailViewModel.MomentUpData) = with(binding){
        btnUp.text = momentUp.upNum.toString()
        btnUp.isSelected = momentUp.isUp
    }

    private val momentDetailItemCallback = object: MomentDetailItemCallback{
        override fun shareContentClicked(view: View, item: MomentListItem.MomentShareItem) {
            when(item.type){
                MOMENT_SHARE_TYPE_ALBUM ->{
                    val transitionName = getString(R.string.album_detail_transition_name)
                    val extra = FragmentNavigatorExtras(view to transitionName)
                    findNavController().navigate(
                        NavAlbumDirections.actionGlobalAlbumDetailFragment(item.id),extra
                    )
                }
                MOMENT_SHARE_TYPE_PLAYLIST ->{
                    val transitionName = getString(R.string.playlist_detail_transition_name)
                    val extra = FragmentNavigatorExtras(view to transitionName)

                    findNavController().navigate(
                        NavPlaylistSheetDirections.actionGlobalPlaylistSheetDetailFragment(item.id),extra
                    )
                }
                MOMENT_SHARE_TYPE_MUSIC ->{
                    musicInfoViewModel.prepareMusic(item.id)
                }
            }
        }

    }

    private val imageCallback = object: CornerImageWrapperView.ImageEventListener<MomentListItem.MomentImageItem>{
        override fun imageClick(view: View, position: Int, imageList: List<MomentListItem.MomentImageItem>) {
            findNavController().navigate(
                ImageBrowseActivityDirections.actionGlobalImageBrowseActivity(
                ImageBrowseData(position,imageList.map {
                    ImageViewData(it.id,it.imageUrl)
                })
            ))
        }

    }

    class ParentCommentRVAdapter(
        private val parentItemCallback: CommentItemCallback,
        private val replyItemCallback: ReplyLayout.ReplayItemCallback
    ): PagingAdapter<MomentCommentItem,
            ParentCommentRVAdapter.ParentCommentViewHolder,MomentDetailParentCommentItemBinding>(
        MomentCommentItem.differCallback){

        override fun createPagingViewHolder(
            parent: ViewGroup,
            viewType: Int
        ): ParentCommentViewHolder {
            return ParentCommentViewHolder(
                MomentDetailParentCommentItemBinding.inflate(LayoutInflater.from(parent.context),parent,false)
            )
        }

        override fun bindPagingItem(
            holder: ParentCommentViewHolder,
            position: Int,
            item: MomentCommentItem?,
            payloads: MutableList<Any>
        ) {
            handleMomentParentComment(holder,item)
        }

        private fun handleMomentParentComment(holder: ParentCommentViewHolder, item: MomentCommentItem?){
            item?.let {
                holder.item = it
                holder.binding.tvMomentParentCommentContent.text = item.commentContent
                holder.binding.tvCommentDatetime.text = item.publishTime
                holder.binding.tvMomentParentCommentAccountName.text = item.userName
                Glide.with(holder.binding.ivMomentParentCommentHeadImg)
                    .load(item.userPhotoUrl)
                    .placeholder(R.drawable.img_default_artist_small)
                    .into(holder.binding.ivMomentParentCommentHeadImg)

                holder.binding.replayLayout.getAdapter()?.subReplayList(item.replayList,item.replayCount)
            }
        }

        inner class ParentCommentViewHolder(binding: MomentDetailParentCommentItemBinding) :
            ViewBindViewHolder<MomentDetailParentCommentItemBinding>(binding){

            var item: MomentCommentItem? = null

            init {
                binding.replayLayout.setAdapter(ReplyLayout.ReplayLayoutAdapter(replyItemCallback))

                binding.root.setOnClickListener {
                    item?.let { data ->
                        parentItemCallback.commentItemClicked(it,data)
                    }
                }
            }
        }

    }

    private val parentItemCallback = object: CommentItemCallback {

        override fun commentItemClicked(view: View, item: MomentCommentItem) {
            findNavController().navigate(
                MomentDetailFragmentDirections.actionMomentDetailFragmentToPublishCommentFragment(
                    PublishCommentData(
                        item.momentId,
                        COMMENT_TYPE_REPLAY, item.userId,
                        item.userName,
                        item.id
                    )
                )
            )
        }

    }

    private val replayItemCallback = object: ReplyLayout.ReplayItemCallback{

        override fun replayItemClicked(view: View, item: MomentReplayItem) {
            findNavController().navigate(
                MomentDetailFragmentDirections.actionMomentDetailFragmentToPublishCommentFragment(
                    PublishCommentData(
                        item.momentId,
                        COMMENT_TYPE_REPLAY_REPLAY, item.userId,
                        item.userName,
                        item.commentId
                    )
                )
            )

        }

        override fun moreClicked(view: View, item: MomentReplayItem) {
            findNavController().navigate(
                MomentDetailFragmentDirections.actionMomentDetailFragmentToReplayListFragment(
                    item.commentId
                )
            )
        }

    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

const val REFRESH_MOMENT_KEY = "refresh_moment"